/***************************************************************************
* Copyright  Faraday Technology Corp 2002-2003.  All rights reserved.      *
*--------------------------------------------------------------------------*
* Name:fiq.c                                                               *
* Description: Fast interrupt library routine                              *
* Author:                                                        *
****************************************************************************/
#include "unione_lite.h"
#include "interrupt.h"
#include "DrvUART010.h"

volatile UINT32 *FIQBase = (UINT32 *)INTC_FTINTC020_PA_BASE;

fLib_INT FIQVector[PLATFORM_FIQ_TOTALCOUNT]={0};
UINT32 FIQSources = 0;//define the current irq source for debug
extern UINT32 get_irqnum(UINT32 flags);
/* define FIQ trap and handler routine */
//PrVoid fLib_NewFIQTrap = (PrVoid) 0;	
//PrHandler fLib_FIQHandle = (PrHandler) 0;
//PrVoid fLib_OldFIQTrap = (PrVoid) 0;	


#if NR_FIQS > PLATFORM_FIQ_TOTALCOUNT
#  error Unable to handle more than 32 FIQ levels.
#endif

/////////////////////////////////////////////////////
//
//	Only for detail function call subroutine
//
/////////////////////////////////////////////////////

/*  Turn the interrupt source off. */
void MaskFIQ(UINT32 FIQ)
{    
    FIQBase[(FIQ_MASK / sizeof(UINT32))] &= ~(1 << FIQ);
}

/*  Turn the interrupt source on */
void UnmaskFIQ(UINT32 FIQ)
{
    FIQBase[(FIQ_MASK / sizeof(UINT32))] |= (1 << FIQ);
}
void SetFIQmode(UINT32 FIQ,UINT32 edge)
{
     if(edge) 
    	FIQBase[(FIQ_MODE / sizeof(UINT32))] |= (1 << FIQ);
    else
    	FIQBase[(FIQ_MODE / sizeof(UINT32))] &= ~(1 << FIQ);	
}	

void SetFIQlevel(UINT32 FIQ,UINT32 low)
{
    if(low) 
    	FIQBase[(FIQ_LEVEL / sizeof(UINT32))] |= (1 << FIQ);
    else
    	FIQBase[(FIQ_LEVEL / sizeof(UINT32))] &= ~(1 << FIQ);	
}	

void ClearFIQStatus(UINT32 FIQ)
{
 	FIQBase[(FIQ_CLEAR / sizeof(UINT32))] |= (1 << FIQ);
}

/*
 * Interrupt service routine dispatcher.
 *
 * This is the FIQ handler called when an FIQ trap is taken.
 */
 /*
 http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0491c/BABICJBC.html
 The __irq keyword enables a C or C++ function to be used as an interrupt routine.
 Restrictions:
 No arguments or return values can be used with __irq functions.
 Note:
 In architectures other than ARMv6-M and ARMv7-M, the function exits by setting the program counter to lr-4 and the CPSR to the value in SPSR.
 In ARMv6-M and ARMv7-M, specifying __irq does not affect the behavior of the compiled output. However, ARM recommends using __irq on exception
 handlers for clarity and easier software porting.
 For architectures that support ARM and 32-bit Thumb, for example ARMv6T2, ARMv7-A, and ARMv7-R, functions specified as __irq compile to ARM or 
 Thumb code depending on whether the compile option or #pragma specify ARM or Thumb.
 For Thumb only architectures, for example ARMv6-M and ARMv7-M, functions specified as __irq compile to Thumb code.
 For architectures before ARMv6T2, functions specified as __irq compile to ARM code even if you compile with --thumb or #pragma thumb.
 */
void DispatchFIQ(void)// For architectures before ARMv6T2(FA606TE is v5 architecture), functions specified as __irq compile to ARM code even if you compile with --thumb or #pragma thumb.
{
    UINT32 FIQ = 0;
    UINT32 flags;
    fLib_INT *action;
	flags=inw(INTC_FTINTC020_PA_BASE+FIQ_STATUS);
    // Test to see if there is a flag set, if not then don't do anything
    //fLib_printf("%x\n",flags);
    do
    {
		if((flags&0x01)==0x01)
		{
			// Get the vector and process the interrupt.
	        action = &FIQVector[FIQ];
			//#ifdef SHOW_DEBUG_MESSAGE
	        if (action->Handler == NULL)                   
	           fLib_printf("No handler installed\n");       
	        else 
	        //#endif
	           action->Handler(action->IntNum);//action->Handler(FIQ);
		}
		flags>>=1;
		if(flags == 0x00)
			break;
		FIQ++;
    }while(FIQ<32);
}
// End of file - FIQ.c
